承上篇 出處 , 有簡體版 , 進入後自行點選
MDN Node & Express 的綱目是: 介紹 、 安裝開發環境 、 教學 part1~7
照進度來看在結束鐵人賽只會寫到教學 part1 ,
結束後再一週產出一兩篇把它寫完就好
!! 我決定把 middleware
縮寫為 mw
!!
Express app 會很常用到 mw , 包括處理一些 server 靜態檔案的問題 、 壓縮 HTTP res 。Route function
以回傳 res to HTTP client 來結束 HTTP req-res cycle ; mw function
在處理 req 或 res 之後會呼叫放在 stack
的 next function
, 這個 next
可能會是更多的 mw ( 或更多的 routes ) , mw
呼叫順序由開發者自行決定
Note : mw 可以換置 req & res obj 、 執行任何 code 、 還可以結束 req-res cycle , 如果 cycle 沒有被結束 , 它必須繼續呼叫 next()
傳遞控制訊息到下一個 mw function ( 否則 req 會被擺著沒人理 , 原文 be left hanging
)
多數 app 會用第三方 mw , 為的是簡化常見的網站開發任務 , 例如 : cookies, sessions, authentucation, accessing req POST & JSON data, logging ... , 可以點這裡 list of middleware packages maintained by the Express team 查看提到的內容 。 其他 Express packages 可以用 NPM 取得
要用第三方 mw 前 , 我們要先用 NPM 安裝 。 例如:安裝 morgan HTTP req logger mwmorgan
究竟是啥? 參考連結: [Node.js打造API] 新增 middleware(body-parser、cors、morgan) 作者 (https://github.com/andy6804tw) , 這篇文章超白話易懂 , 大推 !
簡單來說會幫我們記下一些 req 狀態內容的工具 , status code 200, 404 ... 那些的
回到範例 :
$ npm install morgan
接著在 Express app obj 用 use()
, 把 mw 新增到 stack 裡面
var express = require('express');
var logger = require('morgan');
var app = express();
app.use(logger('dev'));
...
Note: Mw & routing functions 需要注意呼叫的順序 , 有些 mw 順序影響很大 , 例: 如果 session mw 依存在 cookie mw 之下 , 那麼 cookie handler 就必須先加入。 通常設定 routes 之前 mw 會先被呼叫, 否則 route handlers 將無法存取我們新增的 mw ( 最後這句與簡中版有衝突, 待查證 )
我們可以寫屬於自己的 mw functions , 這也可能是必須的 ( 如果只有建造處理 error handling code (蛤?) ) 。 Mw function & route handler callback 兩者的唯一不同處是 mw 有第三個參數 next
, 這個 next
是 mw 先預備起來, 如果未完成 req cycle 就拿來呼叫用的
用 app.use()
或 app.add()
(註) 新增 mw function 到作業鏈中 , 而要選用何者? 這取決於是否要將 mw 應用在所有 res 還是特定 HTTP 行為的 res 就好 ; 兩者都可以設定同個路由, 雖然在呼叫 app.use()
時路由設定是非必要的
下方範例演示如何用兩種方式新增 mw function , 同時也有路由設定與未設定:
var express = require('express');
var app = express();
// middleware function 範例
var a_middleware_function = function(req, res, next) {
// ... 其他程式碼
next(); // 呼叫 next() , Express 會呼叫在這個作業鏈中的 next middleware function.
}
// 用 use() 新增 , 所有 routes and verbs 的情況
app.use(a_middleware_function);
// 用 use() 新增 , 指定 route 的情況
app.use('/someroute', a_middleware_function);
// 新增一個 middleware function , 指定 HTTP verb and route 的情況
app.get('/', a_middleware_function);
app.listen(3000);
註: 我認為上面的 app.add()
可能是 .add()
意指要用 .get()/.post() ...
來代換 , 因 MDN 本身舉例的 code 裡面沒有 .add()
, 官網搜尋及列表裡也沒看到 .add()
method (http://expressjs.com/zh-tw/api.html) ; 有確定之後再回頭來改
JS Tips: 上例我們單獨宣告 mw function, 然後把它設為 callback。 在先前的 route handler function 中, 它被使用時我們也把它宣告為 callback 。 在 JS 中兩個都可以
Express 官方文件有更多說明, 請點選 using & writing Express mw ( 這兩個連結都是官方中文版喔!!
)
用 express.static mw 處理靜態檔案, 包括 img, CSS, JS ( .static()
是 Express 的原生 mw ) 。 以下範例是在 serve 跟呼叫 node 同目錄下 public
資料夾裡的靜態檔 ( img, CSS, JS ... )
app.use(express.static('public));
完整寫法
const express = require('express')
const app = express()
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
app.use(express.static('public));
當前資料夾結構 ( 如果沒顯示點這裡 )
所有 public 資料夾的檔案都被 serve 過 , 可以用 URL 來開它們了 , 如:
http://localhost:3000/images/logo.jpg
也可以 serve 多個資料夾目錄 , 如果 mw function 找不到某個文件 , 它會傳給後續的 mw , 會受到 mw 書寫順序的影響
app.use(express.static('public'));
app.use(express.static('media'));
可以為靜態 URL 增加前綴 , 讓這些檔案可以被前綴乘載 。 例如:
app.use('/media', express.static('public'));
http://localhost:3000/media/images/logo.jpg
Serving static files in Express 有更詳細的資訊